using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Xml;

namespace LogAnalyzer
{

    public class DisplayFilter : FilterBase
    {
        private string _queryString = "*";
        private bool _isCaseSensitive;
        private bool _isRegularExpression = false;
        private FontStyle _fontStyle = FontStyle.Regular;
        private Color _foreColor = Color.OrangeRed;
        private Color _backColor = Color.Black;
        private Regex _filterRegEx;


        public DisplayFilter()
        {
            ReCreateRegEx();
        }


        private void ReCreateRegEx()
        {
            _filterRegEx = null;

            string pattern = _queryString;
            if (!_isRegularExpression)
            {
                pattern = Regex.Escape(pattern).Replace(@"\?", ".").Replace(@"\*", ".*");
            }

            RegexOptions options = new RegexOptions();
            if (!_isCaseSensitive) options |= RegexOptions.IgnoreCase;

            _filterRegEx = new Regex(pattern, options);
        }


        [Category("a.  Filter parameters")]
        [DisplayName("Query string")]
        [Description("Set the query for the filter; it can be a regular expression a or simple string with wildcards (*,?)")]
        public string QueryString
        {
            get { return _queryString; }
            set 
            {
                string old = _queryString;

                _queryString = value;
                try
                {
                    ReCreateRegEx();
                }
                catch
                {
                    _queryString = old;
                    throw;
                }

            }
        }

        [Category("a.  Filter parameters")]
        [DisplayName("Is case sensitive")]
        [Description("Set if query os case sensitive or not")]
        public bool IsCaseSensitive
        {
            get { return _isCaseSensitive; }
            set 
            {
                bool old = _isCaseSensitive;
                _isCaseSensitive = value;
                try
                {
                    ReCreateRegEx();
                }
                catch
                {
                    _isCaseSensitive = old;
                    throw;
                }
            }
        }

        [Category("a.  Filter parameters")]
        [DisplayName("Is a regular expression")]
        [Description("Set if query is a regular expression (true) or a simple text with wildcards (false)")]
        public bool IsRegularExpression
        {
            get { return _isRegularExpression; }
            set 
            {
                bool old = _isRegularExpression;
                _isRegularExpression = value;
                try
                {
                    ReCreateRegEx();
                }
                catch
                {
                    _isRegularExpression = old;
                    throw;
                }
            }
        }

        [Category("b.  Display style")]
        [DisplayName("Font style")]
        [Description("Set the font style for matching strings")]
        public FontStyle FontStyle
        {
            get { return _fontStyle; }
            set { _fontStyle = value; }
        }

        [Category("b.  Display style")]
        [DisplayName("Fore color")]
        [Description("Set the fore color for matching strings")]
        public Color ForeColor
        {
            get { return _foreColor; }
            set { _foreColor = value; }
        }

        [Category("b.  Display style")]
        [DisplayName("Back color")]
        [Description("Set the back color for matching strings")]
        public Color BackColor
        {
            get { return _backColor; }
            set { _backColor = value; }
        }



        internal Regex InnerRegex
        {
            get 
            {
                return _filterRegEx;
            }
        }


        private string ColorToString(Color color)
        {
            if (color.IsNamedColor)
                return color.Name;

            string col = "#";
            col += color.R.ToString("X").PadLeft(2, '0');
            col += color.G.ToString("X").PadLeft(2, '0');
            col += color.B.ToString("X").PadLeft(2, '0');
            return col;
        }

        private Color StringToColor(string color)
        {
            if (string.IsNullOrEmpty(color))
                return Color.Empty;

            if (color[0] == '#')
            {
                if (color.Length != 7)
                    return Color.Empty;
                int r = Convert.ToInt32("0x" + color.Substring(1, 2), 16);
                int g = Convert.ToInt32("0x" + color.Substring(3, 2), 16);
                int b = Convert.ToInt32("0x" + color.Substring(5, 2), 16);
                return Color.FromArgb(r, g, b);
            }
            else
            {
                return Color.FromName(color);
            }
        }


        public override void SaveConfig(XmlNode nodeFilter)
        {
            XmlDocument xml = nodeFilter.OwnerDocument;
            
            nodeFilter.Attributes.Append(xml.CreateAttribute("q")).Value = _queryString;
            nodeFilter.Attributes.Append(xml.CreateAttribute("cs")).Value = _isCaseSensitive.ToString();
            nodeFilter.Attributes.Append(xml.CreateAttribute("re")).Value = _isRegularExpression.ToString();
            nodeFilter.Attributes.Append(xml.CreateAttribute("fore")).Value = ColorToString(_foreColor);
            nodeFilter.Attributes.Append(xml.CreateAttribute("back")).Value = ColorToString(_backColor);
            nodeFilter.Attributes.Append(xml.CreateAttribute("style")).Value = ((int)_fontStyle).ToString();

        }

        public override void LoadConfig(XmlNode filterNode)
        {
            _queryString = filterNode.Attributes["q"].Value;
            _isCaseSensitive = bool.Parse(filterNode.Attributes["cs"].Value);
            _isRegularExpression = bool.Parse(filterNode.Attributes["re"].Value);
            _fontStyle = (FontStyle)int.Parse(filterNode.Attributes["style"].Value);
            _foreColor = StringToColor(filterNode.Attributes["fore"].Value);
            _backColor = StringToColor(filterNode.Attributes["back"].Value);

            ReCreateRegEx();
        }

        public override string ToString()
        {
            return QueryString;
        }

        public override FilterBase Clone()
        {
            return (FilterBase)this.MemberwiseClone();
        }

    }
}